home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / pctjsp86.arc / KWIKKEY.ASM < prev    next >
Assembly Source File  |  1986-07-01  |  11KB  |  255 lines

  1. ;----------------------------------------------------------------- 
  2. ; KWIKKEY.ASM  Version 1.4                                  5-28-86 
  3. ; Copyright (c) 1985 by Dan Rollins    
  4. ; This program speeds up the repeat action of the IBM PC and XT 
  5. ; keyboard. After installation, a keystroke begins repeating about 
  6. ; 1/4 second after the initial keystroke and the repeats occur at 
  7. ; about twice the normal speed. These delay and rate parameters may 
  8. ; be modified. The program uses the 55ms timer interrupt to augment 
  9. ; the speed of the keyboard. The basic idea is to have the timer 
  10. ; interrupt check to see if the key has been released. If not, then 
  11. ; it stuffs a keystroke into the BIOS keyboard buffer. Notes: This 
  12. ; program must be used with DOS 2.x or later.  It is a COM format 
  13. ; program, so it must be processed by EXE2BIN. 
  14. ;------------------------------------------------------------------
  15. ;=== program equates ===
  16.  
  17. REPT_DELAY    equ     5  ;number of 55ms intervals to skip before
  18.                          ; the first repeat.  5 = 275ms = about 
  19.                          ; 1/4 second.   Use at least 2 to avoid 
  20.              ; "key bounce"
  21.  
  22. REPT_RATE     equ     1  ;Select from:   0 = 29 repeats per second
  23.                          ;               1 = 20 repeats per second
  24.                          ;               2 = 16 repeats per second
  25.                          ;               3 = 13 repeats per second
  26.                          ;       4 or more = standard repeat rate
  27.  
  28. BIOS_DATA_SEG equ     40h  ;These addresses are listed
  29. BUF_START     equ     1eh  ; in the Technical Reference manual
  30. BUF_END       equ     3eh
  31. BUF_HEAD_ADDR equ     1ah
  32. BUF_TAIL_ADDR equ     1ch
  33. ALT_NUM_BUF   equ     19h
  34.  
  35. FALSE         equ     0
  36. TRUE          equ     1
  37.  
  38. ;=========================
  39.  
  40. com_seg  segment
  41.          assume  cs:com_seg, ds:com_seg
  42.          org     100h                    ;must set up for COM file
  43. kwikkey  proc    far
  44.          jmp     set_up    ;get past the data and install the
  45.                            ;interrupt handlers
  46.  
  47. ;============= program data area ========
  48. delay          db    REPT_DELAY  ;max ticks BEFORE STARTING to repeat
  49. rate           db    REPT_RATE   ;maximum ticks BETWEEN repeats
  50.  
  51. inst_flag      dw    1234h   ;KWIKKEY signature when already installed
  52.  
  53. rep_ok         db    FALSE   ;flag turns off repeat while processing
  54. last_key       dw    0       ;stores most recent keyboard scan code
  55.  
  56. init_delay     db    REPT_DELAY  ;remaining ticks before 
  57.                             ;starting to repeat
  58. rate_delay     db    REPT_RATE   ;remaining tick between repeats
  59.  
  60. bios_kbd_int   label dword   ;DWORD so it can be used in a FAR call
  61. bki_offset     dw    0       ; This is set to the addr of BIOS KB_INT
  62. bki_segment    dw    0       ; at the time of installation of KWIKKEY
  63.  
  64. user_timer_int label  dword  ;used to preserve "forward chain" of user
  65. uti_offset     dw    0       ;timer interrupt handlers.  Set in SET_UP
  66. uti_segment    dw    0       ;procedure, this addr will normally point 
  67.                              ;to an IRET.
  68.  
  69.  
  70. ;---------------------------------------------------------------------
  71. ; KBD_INT
  72. ; This procedure intercepts keystrokes and sends control to normal 
  73. ; BIOS KB_INT.  Its primary function is to set up for the repeat action 
  74. ; that occurs in the TIMER_INT.  It checks each key that comes in, and
  75. ; resets a delay counter if it is a new keystroke.
  76.  
  77. kbd_int  proc    far
  78.          mov     cs:rep_ok,FALSE       ;turn off repeats while 
  79.                     ;processing
  80.          push    ax                    ;save the registers
  81.          push    si
  82.          push    ds
  83.          mov     ax,BIOS_DATA_SEG      ; set up to address 
  84.          mov     ds,ax                 ; BIOS data area
  85.          mov     si,ds:[BUF_TAIL_ADDR] ;get addr of current 
  86.                     ;buffer tail
  87.  
  88.         ;check special case: don't repeat ALT-numpad keystrokes
  89.  
  90.          cmp     byte ptr ds:[ALT_NUM_BUF],0 ;is one in progress?
  91.          je      ki_10                       ; no, continue
  92.          pushf                               ; yes, process 
  93.          call    cs:bios_kbd_int             ; the keystroke
  94.          jmp     ki_exit                     ; exit with repeats off
  95. ki_10:
  96.          pushf                          ;simulate a normal interrupt
  97.          call    cs:bios_kbd_int        ; and process the keystroke
  98.  
  99.          cmp     si,ds:[BUF_TAIL_ADDR]  ;did the tail move?
  100.          jne     ki_20                  ; no, either a shift-key 
  101.                     ; or a release
  102.          mov     cs:last_key,0          ; insure no spurious repeats
  103.          jmp     ki_exit                ; exit with repeats turned off
  104. ki_20:                                  ; yes, process the keystroke
  105.          mov     ax,[si]                ; get new scan code
  106.          cmp     ax,cs:[last_key]       ; same as last time?
  107.          mov     cs:last_key,ax         ; (save the key for next time)
  108.          je      ki_30                  ;  yes, hardware repeat 
  109.                                         ;       just reset the rate
  110.                                         ;  no, reset both timer delays
  111.          mov     al,cs:delay            ;  get maximum tick count
  112.          mov     cs:init_delay,al       ;  set delay before repeat
  113. ki_30:
  114.          mov     al,cs:rate             ;    get maximum tick value
  115.          mov     cs:rate_delay,al       ;    set delay between repeats
  116.          mov     cs:rep_ok,TRUE         ;  OK to continue repeating
  117.  
  118. ki_exit:
  119.          pop     ds
  120.          pop     si
  121.          pop     ax
  122.          iret                     ;also restores Flags of interruptee
  123. kbd_int  endp
  124.  
  125.  
  126. ;---------------------------------------------------------------------
  127. ; TIMER_INT
  128. ; This procedure is executed 18.2 times per second
  129. ;
  130. ; It checks to see if a repeat is needed.  If so, it stuffs the scan 
  131. ; code into the keyboard buffer, ready for the next keystroke request
  132. ;
  133. timer_int proc far
  134.          cmp     cs:[rep_ok],TRUE    ;are repeats blocked?
  135.          jne     ti_exit             ;   yes, resume without repeat
  136.  
  137.          cmp     cs:init_delay,0   ;finished delaying before 
  138.                 ;first repeat?
  139.          je      ti_10             ;   yes, check rate delay
  140.          dec     cs:init_delay     ;   no, decrement timer
  141.          jmp     ti_exit           ;       and resume without repeat
  142.  
  143. ti_10:
  144.          cmp     cs:rate_delay,0   ;finished delaying between repeats?
  145.          je      ti_20             ;   yes, do the repeat
  146.          dec     cs:rate_delay     ;   no, decrement rate timer
  147.          jmp     ti_exit           ;       and resume without repeat
  148.  
  149. ;------- repeat the previous keystroke -----------
  150.  
  151. ti_20:
  152.          push    ax                     ;save all registers used
  153.          push    si
  154.          push    ds
  155.  
  156.          mov     ax,BIOS_DATA_SEG  ;prepare to address BIOS data area
  157.          mov     ds,ax
  158.          mov     ax,ds:[BUF_TAIL_ADDR]  ;get current position 
  159.                     ;in kbd buffer
  160.          mov     si,ax                  ;we'll need this address later
  161.          add     ax,2                   ;point to next position in buffer
  162.          cmp     ax,BUF_END             ;past end of buffer?
  163.          jne     ti_30                  ;  no, continue
  164.          mov     ax,BUF_START           ;  yes, next position is the 
  165.                                         ;start
  166. ti_30:
  167.          cmp     ax,ds:[BUF_HEAD_ADDR]  ;if tail=head, buffer is full
  168.          je      ti_40                  ;full, continue without repeat
  169.          cli                            ;not full, dont allow break-in
  170.          mov     ds:[BUF_TAIL_ADDR],ax  ;      update buffer position
  171.          mov     ax,cs:[last_key]       ;      fetch key to repeat
  172.          mov     [si],ax                ;      store key in buffer
  173.          sti                            ;      interrupts ok now
  174. ti_40:
  175.          mov     al,cs:rate             ;get the max rate delay value
  176.          mov     cs:rate_delay,al       ;don't repeat for a while
  177.          pop     ds                     ;restore registers
  178.          pop     si                     ; and exit
  179.          pop     ax
  180. ti_exit:
  181.          jmp     cs:[user_timer_int]    ;continue with previously 
  182.                                         ;installed interrupt handler 
  183. timer_int endp
  184.  
  185. LAST_BYTE equ   offset $+1  ;this is the address passed to INT 27H
  186.                             ; Notice that the code of the SET_UP
  187.                             ; procedure does not need to be preserved
  188.  
  189. ;---------------------------------------------------------------------
  190. ; SET_UP
  191. ; This routine is executed only once -- when the program is installed.
  192. ;
  193. ; It resets the vectors of the KBD_INT and the USER_TIMER_INT, 
  194. ; pointing them to code within this program.  Note that the original 
  195. ; vectors are saved and executed so all previously-installed interrupt
  196. ; handlers remain operational.
  197.  
  198. logo_msg db 201, 25 dup(205),187,0dh,0ah
  199.          db 186,'    KWIKKEY  Ver. 1.4    ',186,0dh,0ah
  200.          db 186,' (c) 1986 by Dan Rollins ',186,0dh,0ah
  201.          db 200, 25 dup(205),188,0dh,0ah,'$'
  202.  
  203. err_msg  db 'Error: ',07,'KWIKKEY already installed',0dh,0ah,'$'
  204.  
  205. set_up   proc    near
  206.          ;------ first, make sure KWIKKEY hasn't been installed ---
  207.          mov     al,9
  208.          mov     ah,35h              ;DOS GET_VECTOR service
  209.          int     21h                 ; for interrupt 9
  210.  
  211.          cmp     es:inst_flag,1234h  ;has KWIKKEY been installed?
  212.          jne     su_10               ; no, continue
  213.          mov     dx,offset err_msg   ; yes, display
  214.          mov     ah,9                ;       error
  215.          int     21h                 ;        message
  216.          int     20h                 ;and exit to DOS
  217. su_10:
  218.          mov     al,9           ;get original vector of keyboard int 9
  219.          mov     ah,35h         ;DOS GET_VECTOR service
  220.          int     21h
  221.          mov     bki_segment,es ;save original address
  222.          mov     bki_offset,bx  ; so we can resume normally 
  223.                           ; after intercept
  224.          mov     dx,offset kbd_int
  225.          mov     al,9           ;set vector for INT 9
  226.          mov     ah,25h         ;DOS SET_VECTOR service
  227.          int     21h
  228.  
  229.          mov     al,1ch         ;the user timer interrupt
  230.          mov     ah,35h         ;DOS GET_VECTOR service
  231.          int     21h
  232.          mov     uti_segment,es ;save old address
  233.          mov     uti_offset,bx  ; so we don't hog the timer interrupt
  234.  
  235.          mov     dx,offset timer_int
  236.          mov     al,1ch        ;set vector to point to new TIMER_INT
  237.          mov     ah,25h        ;DOS SET_VECTOR service
  238.          int     21h
  239.  
  240.          ;------ display logo to indicate installation complete
  241.          mov     dx,offset logo_msg
  242.          mov     ah,9
  243.          int     21h
  244.  
  245.          mov     cs:rep_ok,TRUE   ; it's OK to start repeat action
  246.  
  247.          ;------ exit to DOS, leaving the interrupt handlers resident
  248.          mov     dx,LAST_BYTE
  249.          int     27h
  250. set_up   endp
  251. kwikkey  endp
  252. com_seg  ends
  253.          end     kwikkey       ;must specify for COM-format file
  254.